<?php
namespace app\api\controller;
use addons\jiezicommon\service\Tools;
use app\common\controller\Api;
use app\common\model\Team;
use EasyWeChat\Factory;
use think\Db;
use think\Validate;

/**
 * 订单
 */
class Order extends Api
{
    protected $noNeedRight = ['*'];
    protected $noNeedLogin = ['notice', 'refund', 'auto_cancel', 'auto_receive'];

    /**
     * 订单列表
     * @ApiMethod (POST)
     * @ApiParams (name="page", type="int", required=true, sample="", default="1", description="页码")
     * @ApiParams (name="limit", type="int", required=true, sample="", default="10", description="每页数量")
     * @ApiParams (name="status", type="int", required=true, sample="", default="0", description="订单状态:0=全部,1=待确认,2=待发货,3=待收货")
     */
    public function get_list(){
        \think\Lang::load(APP_PATH . 'admin/lang/zh-cn/order.php');
        $params = input();
        $page = empty($params['page']) ? 1 : intval($params['page']);
        $limit = empty($params['limit']) ? 10 : intval($params['limit']);
        $keyword = xss_clean($params['keyword'] ?? "");
        $status = empty($params['status']) ? 0 : intval($params['status']);
        if($status < 0 || $status > 3){
            $status = 0;
        }
        //订单状态:1=待支付,2=已支付,3=已取消
        $table = (new \app\common\model\Order())->alias('o');
        $table->where('o.user_id', $this->auth->id);
        if($status == 1){
            $table->where('o.status', '1');
        }
        if($status == 2){
            $table->where('o.status', '3');
        }
        if($status == 3){
            $table->where('o.status', '4');
        }
        if($status == 0){
            $table->where('o.status', 'in', '1,2,3,4,9');
        }
        $fields = 'o.id, o.order_sn,o.status,o.order_amount, o.cost_freight';
        $res = $table->field($fields)->order('o.id desc')
        ->paginate($limit, false, ['page' => $page])
            ->each(function($item){
                $goods = \app\common\model\OrderItems::alias('os')
                    ->where(['order_id' => $item['id']])
                    ->select();
                $goods_list = [];
                foreach($goods as $g){
                    $images = $g['images'] ? Tools::str2arr($g['images'], ',', 'cdnurl', true, [true]) : [];
                    $image = !empty($images[0]) ? $images[0] : '';
                    $t = [
                        'id' => $g['id'],
                        'name' => $g['name'],
                        'spes' => $g['spes'],
                        'images' => $images,
                        'image' => $image,
                        'price' => $g['price'],
                        'nums' => $g['nums'],
                    ];
                    $goods_list[] = $t;
                }
                $item['goods'] = $goods_list;
            })
        ;
        $return_data = [
            'total' => $res->total(),
            'list' => $res->items(),
            'sql' => $table->getLastSql(),
        ];
        $this->success('ok', $return_data);
    }

    /**
     * 订单详细
     * @ApiMethod (POST)
     * @ApiParams (name="id", type="int", required=true, sample="", default="1", description="订单id")
     * @return void
     */
    public function get_info($id = null, $sn = null){
        if($sn){
            $order = \app\common\model\Order::get(['order_sn|out_trade_no' => $sn]);
        }else{
            $order = \app\common\model\Order::get($id);
        }

        if(empty($order)){
            $this->error('订单不存在');
        }
        if($order['user_id'] != $this->auth->id){
            $this->error('错误的订单');
        }
        $return_data = [
            'order' => [],
            'goods' => [],
        ];
        if($order['status'] == 1){

        }
        $return_data['order']['id'] = $order->id;
        $return_data['order']['order_sn'] = $order->order_sn;
        $return_data['order']['status'] = $order->status;
        $return_data['order']['order_amount'] = $order->order_amount;
        $return_data['order']['ship_name'] = $order->ship_name;
        $return_data['order']['ship_mobile'] = $order->ship_mobile;
        $return_data['order']['ship_address'] = $order->ship_address;
        $return_data['order']['createtime'] = $order->createtime;
        $return_data['order']['now'] = time();
        $cancel_remain_time = ($order->createtime + (config('unpaid_cancel_time') ?? 3600)) - time();

        $return_data['order']['cancel_remain_time'] = $cancel_remain_time > 0 ? $cancel_remain_time : 0;

        $goods = \app\common\model\OrderItems::alias('os')
            ->where(['order_id' => $order['id']])
            ->select();
        $goods_list = [];
        foreach($goods as $g){
            $images = $g['images'] ? Tools::str2arr($g['images'], ',', 'cdnurl', true, [true]) : [];
            $image = !empty($images[0]) ? $images[0] : '';
            $t = [
                'id' => $g['id'],
                'name' => $g['name'],
                'spes' => $g['spes'],
                'images' => $images,
                'image' => $image,
                'price' => $g['price'],
                'nums' => $g['nums'],
            ];
            $goods_list[] = $t;
        }
        $return_data['goods'] = $goods_list;

        $this->success('ok', $return_data);
    }

    /**
     * 下单
     * @ApiMethod (POST)
     * @ApiParams (name="address_id", type="int", required=true, sample="", default="1", description="收货地址id")
     * @ApiParams (name="goods_id", type="int", required=true, sample="", default="1", description="商品id")
     * @ApiParams (name="goods_spec", type="string", required=false, sample="", default="1", description="商品规格")
     * @ApiParams (name="goods_num", type="int", required=true, sample="", default="1", description="商品数量")
     * @return void
     */
    public function quick_order(){
        $address_id = input('address_id/d');
        if($address_id <= 0){
            $this->error('收货地址错误');
        }
        $address = \addons\jieziaddress\model\JieziaddressUserAddress::get($address_id);
        if(empty($address)){
            $this->error('收货地址不存在');
        }
        $goods_id = input('goods_id/d');
        if($goods_id <= 0){
            $this->error('商品参数错误');
        }
        $goods = \app\common\model\Goods::get($goods_id);
        if(empty($goods) || $goods['marketable'] != 1){
            $this->error('商品不存在');
        }
        $goods_num = input('goods_num/d');
        if($goods_num <= 0){
            $goods_num = 1;
        }

        if($goods['stock'] < $goods_num){
            $this->error('库存不足');
        }
        $db_goods_spec_arr = $goods['spes_desc'] ? json_decode($goods['spes_desc'], 1) : [];
        $db_goods_spec_arr = array_column($db_goods_spec_arr, 'name');
//        var_dump($db_goods_spec_arr);die;
        $goods_spec = input('goods_spec');
        if($db_goods_spec_arr){
            if(!in_array($goods_spec, $db_goods_spec_arr)){
                $this->error('错误的规格');
            }
        }else{
            $goods_spec = '';
        }

        $return_data = [];
        //商品总价
        $goods_amount = $goods['price'] * $goods_num;
        //运费
        $cost_freight = 0;
        //订单总额
        $order_amount = $goods_amount + $cost_freight;
        $order_sn = \addons\jiezicommon\service\Tools::getOrderSn();
        Db::startTrans();
        try {
            $order = [
                'order_sn' => $order_sn,
                'out_trade_no' => $order_sn,
                'goods_amount' => $goods_amount,
                'order_amount' => $order_amount,
                'pay_status' => '1',
                'ship_status' => '1',
                'status' => '1',
                'cost_freight' => $cost_freight,
                'user_id' => $this->auth->id,
                'ship_area_id' => $address['district_id'],
                'ship_area' => $address['location'],
                'ship_address' => str_replace('|', ' ', $address['location']) . ($address['address'] ? ' ' . $address['address'] : ''),
                'ship_name' => $address['name'],
                'ship_mobile' => $address['phone'],
                'ip' => request()->ip(),
            ];
            $order_id = \app\common\model\Order::create($order)->getLastInsID();
            $return_data['order_id'] = $order_id;
            $return_data['sn'] = $order_sn;
            $order_items = [
                'order_id' => $order_id,
                'user_id' => $order['user_id'],
                'goods_id' => $goods_id,
                'name' => $goods['name'],
                'price' => $goods['price'],
                'costprice' => $goods['costprice'],
                'mktprice' => $goods['mktprice'],
                'images' => $goods['images'],
                'spes' => $goods_spec,
                'nums' => $goods_num,
                'amount' => $goods_amount,
            ];
            \app\common\model\OrderItems::create($order_items);
            $config = Tools::getMiniProgram();
            $title = '购买商品';
            $third = $this->auth->getUser()->getThird();
            $openid = $third['openid'] ?? '';
            $notify_url = request()->domain() . '/api/order/notice';

            //不需支付
            $need_pay = false;
            if($need_pay){
                $payment = Factory::payment($config);
                $mer_data = [
                    'body' => $title,
                    'out_trade_no' => $order_sn,
                    'total_fee' => $order_amount * 100,//分
    //                  'spbill_create_ip' => request()->ip(),
                    'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                    'openid' => $openid,
                    'notify_url' => $notify_url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
                ];
    //                var_dump($config, $mer_data);die;
                \think\Log::write('get_pay_info:' . var_export($mer_data, true) . PHP_EOL);

                $result = $payment->order->unify($mer_data);
                if ($result['return_code'] != 'SUCCESS') {
                    Db::rollback();
                    throw new \Exception($result['return_msg']);
    //                    $this->error($result['return_msg']);
                }
                if ($result['result_code'] != 'SUCCESS') {
                    Db::rollback();
                    throw new \Exception($result['err_code_des']);
    //                    $this->result($result['err_code_des']);
                }
    //        var_dump($result);die;
                $jssdk = $payment->jssdk;
                $return_data['pay_info'] = $jssdk->sdkConfig($result['prepay_id']);
            }
            Db::commit();
        }catch (\think\Exception $e){
            Db::rollback();
            $this->error($e->getMessage());
        }
        $this->success('', $return_data);
    }

    /**
     * 旧订单支付
     * @ApiMethod (POST)
     * @ApiParams (name="id", type="int", required=true, sample="", default="1", description="订单id")
     * @ApiInternal
     * @return void
     * @throws \Yansongda\Pay\Exception\ContainerException
     * @throws \think\exception\DbException
     */
    public function old_order_pay($id = null){
        $this->error('');

        $order = \app\common\model\Order::get($id);
        if(empty($order)){
            $this->error('订单不存在');
        }
        if($order['user_id'] != $this->auth->id){
            $this->error('错误的订单');
        }

        if($order['status'] != 1){
            $this->error('订单状态错误');
        }

        $need_pay = true;
        $return_data = [
            'need_pay' => $need_pay,
            'pay_info' => [],
        ];

        if($need_pay){
            $order_sn = \addons\jiezicommon\service\Tools::getOrderSn();
            //修改重新发起支付
            $order->out_trade_no = $order_sn;
            $order->save();
            $config = Tools::getMiniProgram();
            $title = '购买商品';
            $third = $this->auth->getUser()->getThird();
            $openid = $third['openid'] ?? '';
            $notify_url = request()->domain() . '/api/order/notice';

            $payment = Factory::payment($config);
            $total_money = $order['order_amount'];
            $mer_data = [
                'body' => $title,
                'out_trade_no' => $order_sn,
                'total_fee' => $total_money * 100,//分
//                  'spbill_create_ip' => request()->ip(),
                'trade_type' => 'JSAPI', // 请对应换成你的支付方式对应的值类型
                'openid' => $openid,
                'notify_url' => $notify_url, // 支付结果通知网址，如果不设置则会使用配置里的默认地址
            ];
//                var_dump($config, $mer_data);die;
            \think\Log::write('get_pay_info:' . var_export($mer_data, true) . PHP_EOL);

            $result = $payment->order->unify($mer_data);
            if ($result['return_code'] != 'SUCCESS') {
                Db::rollback();
//                throw new \Exception($result['return_msg']);
                $this->error($result['return_msg']);
            }
            if ($result['result_code'] != 'SUCCESS') {
                Db::rollback();
//                throw new \Exception($result['err_code_des']);
                $this->result($result['err_code_des']);
            }
//        var_dump($result);die;
            $jssdk = $payment->jssdk;
            $return_data['pay_info'] = $jssdk->sdkConfig($result['prepay_id']);
        }
        $this->success(__('ok'), $return_data);
    }

    /**
     * 退款回调
     * @ApiInternal
     */
    public function refund(){
        $this->error('');

        $url_params = input();
        \think\Log::notice('refund_notify data:' . var_export($url_params, 1) . PHP_EOL);

        $config = [
            // 前面的appid什么的也得保留哦
            'app_id' => config('site.mini_app_id'),
            'app_secret' => config('site.mini_app_secret'),
            'mch_id' => config('site.mini_mch_id'),
            'key' => config('site.mini_api_key'),
//                    'sub_mch_id' => config('site.mp_sub_mch_id'),
        ];
        $app = Factory::payment($config);
        $response = $app->handleRefundedNotify(function ($message, $reqInfo, $fail)use($url_params) {
            \think\Log::notice('refund_notify message:' . var_export($message, 1) . PHP_EOL);
            \think\Log::notice('refund_notify reqInfo:' . var_export($reqInfo, 1) . PHP_EOL);

            $r_sn = str_replace('R', '', $reqInfo['out_refund_no']);
            $order = Team::get(['out_trade_no' => $r_sn]);
            // 其中 $message['req_info'] 获取到的是加密信息
            // $reqInfo 为 message['req_info'] 解密后的信息
            // 你的业务逻辑...
            if(!empty($reqInfo['refund_status'])) {
                if ($reqInfo['refund_status'] == 'SUCCESS') {
                    if(!empty($order)) {
                        if ($order['status'] != 9) {
                            $order->status = 9;
                        }

                        if($order['pay_status'] != 3){
                            $order->pay_status = 3;
                            $order->ship_status = 1;
                            $order->refund_fail_reason = '';
                        }
//                        $order->canceltime = time();
                        $order->save();

                        return true; // 返回 true 告诉微信“我已处理完成”
                    }
                }
                $fail($reqInfo['err_code'] . '<->' . $reqInfo['err_code_des']);
            }
            if($message['return_code'] != 'SUCCESS'){
                $fail($reqInfo['return_msg'] . '<====');
            }
            // 或返回错误原因 $fail('参数格式校验错误');
        });

        $response->send();
    }

    /**
     * 订单取消
     * @ApiMethod (POST)
     * @ApiParams (name="id", type="int", required=true, sample="", default="1", description="订单id")
     */
    public function order_cancel(){
        $params = input();
        $order_id = intval($params['id'] ?? 0);
        if($order_id <= 0){
            $this->error('订单不存在');
        }
        $order = \app\common\model\Order::get($order_id);
        if(empty($order) || $order['user_id'] != $this->auth->id){
            $this->error('订单不存在');
        }
        if($order['ship_status'] == 2){
            $this->error('已发货，不能取消');
        }
        if($order['status'] == 9){
            $this->error('订单已取消');
        }
        Db::startTrans();
//        try {
            //发起退款
            //已支付
            if($order['status'] == 2 && $order['order_amount'] > 0 && $order['transaction_id']){
                $myparams['order_id'] = $order['id'];
                $myparams['out_trade_no'] = $order['out_trade_no'];
                $myparams['total_fee'] = number_format($order['order_amount'], 2, '.', '');
                $myparams['refund_fee'] = number_format($order['order_amount'], 2, '.', '');

                $resl = \addons\jiezicommon\service\Tools::refund($myparams);

                if(!empty($resl['return_code']) && $resl['return_code'] != 'SUCCESS'){
                    //发起退款-失败
                    Db::rollback();
                    $this->error('退款失败！' . $resl['return_msg']);
                }
                if (!empty($resl['result_code']) && $resl['result_code'] == 'SUCCESS') {

                } else {
                    //发起退款-失败
                    Db::rollback();
                    $this->error('退款失败！！' . $resl['err_code_des']);
                }
            }else{
                //未支付
                $order->status = 9;
                $order->pay_status = 3;
//                $order->canceltime = time();
                $order->save();
            }
//        }catch (\think\Exception $e){
            /**
             * {
            "code": "40004",
            "msg": "撤销或退款金额与订单金额不一致",
            "time": "1725357084",
            "data": null
            }
             */
//            $refund_data = $e->getData();
//            Db::rollback();
//            if($refund_data){
//                $this->error($refund_data['msg'], null, $refund_data['code']);
//            }else {
//                $this->error($e->getMessage());
//            }
//        }
        Db::commit();
        $this->success('订单取消成功');
    }

    public function auto_cancel(){
        $this->error();
        $result = \app\common\model\Order::where('status', '1')->where('createtime', '<', time() - config('unpaid_cancel_time') ?? 3600)->update(['status' => 9]);
        echo 'success:' . $result;
    }

    /**
     * 支付回调
     * @ApiInternal
     * @ApiMethod (POST)
     */
    public function notice(){
        $this->error('');

        \think\Log::write('notify notice input ' . var_export(input(), true) . PHP_EOL);
        $config = Tools::getInstance()->getMiniProgram();
        $app = Factory::payment($config);
        $response = $app->handlePaidNotify(function ($message, $fail) {
            \think\Log::write('notify notice message ' . var_export($message, true) . PHP_EOL);
            if ($message['return_code'] === 'SUCCESS') { // return_code 表示通信状态，不代表支付状态
//                // 用户是否支付成功
                if ($message['result_code'] === 'SUCCESS') {
                    $order_model = new \app\common\model\Order();
                    $order = $order_model->where('out_trade_no',$message['out_trade_no'])->find();
                    if(empty($order) || $order['pay_status'] == 2){
                        return true;
                    }

                    $third = (new \app\common\model\User())->getThird($order['user_id']);
                    $openid = $third['openid'] ?? '';
                    Db::startTrans();
                    $now = time();
                    try {
                        $order->paytime = $now;
                        $order->transaction_id = $message['transaction_id'];
                        $order->status = 2;
                        $order->pay_status = 2;
                        $order->openid = $openid;
                        $order->save();

                    }catch (\Exception $e){
                        Db::rollback();
                        \think\Log::error('报名回调失败:' . $e->getTraceAsString());
                    }
                    Db::commit();
                }
            }
        });

        $response->send();
    }

    /**
     * 订单收货
     * @ApiMethod (POST)
     * @ApiParams (name="id", type="int", required=true, sample="", default="1", description="订单id")
     */
    public function order_receive(){
        $params = input();
        $order_id = intval($params['id'] ?? 0);
        if($order_id <= 0){
            $this->error('订单不存在');
        }
        $order = \app\common\model\Order::get($order_id);
        if(empty($order) || $order['user_id'] != $this->auth->id){
            $this->error('订单不存在');
        }
        if($order['status'] != 3){
            $this->error('状态异常');
        }
        if($order['status'] == 9){
            $this->error('订单已取消');
        }

        $order->status = 4;
        $order->confirm = 2;
        $order->confirmtime = time();
        $order->save();
        $this->success('订单收货成功');
    }

    public function auto_receive(){
        $result = \app\common\model\Order::where('status', '3')->where('shiptime', '<', time() - config('paid_receive_time') ?? 3600)->update(['status' => 4, 'confirm' => 2, 'confirmtime' => time()]);
        echo 'success:' . $result;
    }
}
